<template>
  <div class="desktop">
    <div class="top">
      <el-dropdown trigger="click">
        <div class="logo"><i class="iconfont icon-apple1"></i></div>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item @click="openAppByKey('system_about')">
              <div>关于我们</div>
            </el-dropdown-item>
            <el-dropdown-item class="line"></el-dropdown-item>
            <el-dropdown-item @click="openAppByKey('system_setting')">
              <div>系统偏好设置</div>
            </el-dropdown-item>
            <el-dropdown-item @click="openAppByKey('system_task')">
              <div>强制退出...</div>
            </el-dropdown-item>
            <el-dropdown-item @click="lockScreen">
              <div>锁定屏幕</div>
            </el-dropdown-item>
            <el-dropdown-item class="line"></el-dropdown-item>
            <el-dropdown-item @click="shutdown">
              <div>关机...</div>
            </el-dropdown-item>
            <el-dropdown-item @click="logout">
              <div>退出登录 {{ userName }}...</div>
            </el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
      <div class="menu" v-for="item in menu" :key="item.value">
        <el-dropdown trigger="click" placement="bottom-start">
          <div class="item">{{ item.title }}</div>
          <template #dropdown>
            <el-dropdown-menu>
              <template v-for="subItem in item.sub" :key="subItem.value">
                <el-dropdown-item
                  class="line"
                  v-if="subItem.isLine"
                ></el-dropdown-item>
                <el-dropdown-item v-else>
                  <div>{{ subItem.title }}</div>
                </el-dropdown-item>
              </template>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <div class="space"></div>
      <div class="status">
        <div
          class="song"
          @click="openAppByKey('song_player')"
          v-show="songInfo"
        >
          <marquee
            onMouseOut="this.start()"
            onMouseOver="this.stop()"
            scrollamount="3"
            >{{ songInfo.name }} - {{ songInfo.artist }}</marquee
          >
          <audio
            ref="audio"
            :src="songUrl"
            autoplay="autoplay"
            @timeupdate="audioTimeUpdate"
            @ended="audioEnded"
            @error="audioError"
            :volume="$store.state.volume / 100"
          ></audio>
        </div>
        <div class="audio">
          <i
            class="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu-39"
            @click="showOrHidevolume"
          ></i>

          <transition name="fade">
            <el-slider
              v-show="isvolumeShow"
              v-model="volume"
              :show-tooltip="false"
              @change="volumeChanged"
              vertical
            ></el-slider>
          </transition>
        </div>
        <div class="datetime" @click.self="showOrHideCalendar">
          {{ timeString }}
          <transition name="fade">
            <el-calendar v-model="nowDate" v-if="isCalendarShow"> </el-calendar>
          </transition>
        </div>
        <div class="notification">
          <i
            class="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu-25"
          ></i>
        </div>
      </div>
    </div>
    <div
      class="body"
      @contextmenu.prevent.self="
        hideAllController();
        openMenu($event);
      "
      @click.stop="hideAllController()"
    >
      <div class="desktop-app">
        <template v-for="item in deskTopAppList" :key="item.key">
          <div
            class="app-item"
            v-on:dblclick="$store.commit('openApp', item)"
            v-if="!item.hideInDesktop"
          >
            <div class="icon">
              <i
                :style="{
                  backgroundColor: item.iconBgColor,
                  color: item.iconColor,
                }"
                class="iconfont"
                :class="item.icon"
              ></i>
            </div>
            <div class="title">{{ item.title }}</div>
          </div>
        </template>
      </div>
      <transition-group name="fade-window">
        <template v-for="item in $store.state.openAppList" :key="item.pid">
          <App
            v-if="!item.outLink"
            v-show="!item.hide"
            :app="item"
            :key="item.pid"
            @sendWssMessage="sendWssMessage"
          ></App>
        </template>
      </transition-group>

      <transition name="fade-menu">
        <div
          v-show="rightMenuVisible"
          :style="{ left: rightMenuLeft + 'px', top: rightMenuTop + 'px' }"
          class="contextmenu"
        >
          <div @click="openRoom()">打开房间</div>
          <hr />
          <div @click="openAppByKey('song_player')">正在播放...</div>
          <div @click="openAppByKey('room_song')" v-if="$store.state.roomInfo">
            已点的歌曲...
          </div>
          <hr />
          <div @click="openAppByKey('system_setting')">偏好设置...</div>
          <div @click="openAppByKey('system_task')">强制退出...</div>
          <hr />
          <div>设置壁纸...</div>
          <div @click="openAppByKey('system_about')">关于我们</div>
        </div>
      </transition>
    </div>
    <Dock></Dock>
    <div class="loading-message" v-if="loading_message">
      {{ loading_message }}
    </div>
  </div>
</template>
<script>
import App from "@/components/App";
import Dock from "@/components/Dock";

import tool from "@/helper/tool";
export default {
  name: "DeskTop",
  components: {
    App,
    Dock,
  },
  data() {
    return {
      isCalendarShow: false,
      nowDate: new Date(),
      volumeDelayTimer: false,
      volume: 80,
      isvolumeShow: false,
      rightMenuVisible: false,
      rightMenuLeft: 0,
      rightMenuTop: 0,
      userName: "",
      loading_message: false,
      wss: false,
      heartBeatTimer: false,
      menu: [],
      timeString: "",
      deskTopAppList: [],
      songInfo: false,
      songUrl: "",
      audioRetryTimes: 0,
      musicLrcObj: false,
      deskTopMenu: [
        // {
        //   key: "desktop",
        //   title: "桌面",
        //   sub: [
        //     {
        //       key: "big_icon",
        //       title: "大图标",
        //     },
        //     {
        //       key: "big_icon",
        //       title: "小图标",
        //     },
        //     {
        //       isLine: true
        //     },
        //     {
        //       key: "align_left",
        //       title: "左侧排列",
        //     },
        //     {
        //       key: "align_right",
        //       title: "右侧排列",
        //     },
        //     {
        //       isLine: true
        //     },
        //     {
        //       key: "wall",
        //       title: "更换壁纸...",
        //     }
        //   ]
        // }
      ],
    };
  },
  watch: {
    "$store.state.showLogin"() {
      if (this.$store.state.showLogin && this.wss) {
        this.wss.close();
      }
    },
    "$store.state.userInfo"() {
      if (this.wss) {
        this.wss.close();
      }
      this.userName = false;
    },

    "$store.state.songInfo": {
      handler(songInfo) {
        if (this.songInfo.mid !== songInfo.mid) {
          this.songInfo = songInfo;
          if (songInfo) {
            this.getLrc();
            this.request({
              url: "song/play",
              method: "post",
              data: {
                mid: songInfo.mid,
              },
              success: (res) => {
                this.songUrl = res.data.url;
                this.audioRetryTimes = 0;
              },
            });
          }
        }
      },
      immediate: true,
      deep: true,
    },
  },
  created() {
    this.menu = this.deskTopMenu;
    this.userName = localStorage.getItem("user_name") || "";
    this.deskTopAppList = this.tool.getDeskTopApp();
    this.startTimer();
    this.$store.commit("getDockAppList");
    this.connectWebsocket();
  },
  methods: {
    volumeChanged() {
      console.log(this.volume);
      this.$store.commit("setvolume", this.volume);
      this.hideVolumeBarDelay();
    },
    hideVolumeBarDelay() {
      clearTimeout(this.volumeDelayTimer);
      this.volumeDelayTimer = setTimeout(() => {
        this.isvolumeShow = false;
      }, 3000);
    },
    /**
     * @description: 显示或隐藏日历
     */
    showOrHideCalendar() {
      this.isCalendarShow = !this.isCalendarShow;
    },
    /**
     * @description: 显示或隐藏音量操作
     */
    showOrHidevolume() {
      this.isvolumeShow = !this.isvolumeShow;
      if (this.isvolumeShow) {
        this.hideVolumeBarDelay();
      }
    },
    /**
     * @description: 隐藏所有弹出的控制器
     */
    hideAllController() {
      this.isvolumeShow = false;
      this.rightMenuVisible = false;
      this.isCalendarShow = false;
    },
    openRoom() {
      if (this.$store.state.roomInfo) {
        this.openAppByKey("room_main");
      } else {
        this.openAppByKey("room_list");
      }
    },
    openMenu(e) {
      const menuMinWidth = 105;
      const offsetLeft = this.$el.getBoundingClientRect().left; // container margin left
      const offsetWidth = this.$el.offsetWidth; // container width
      const maxLeft = offsetWidth - menuMinWidth; // left boundary
      const left = e.clientX - offsetLeft; // margin right

      if (left > maxLeft) {
        this.rightMenuLeft = maxLeft;
      } else {
        this.rightMenuLeft = left;
      }

      this.rightMenuTop = e.clientY - 30;
      this.rightMenuVisible = true;
    },
    getLrc() {
      this.request({
        url: "song/lrc",
        method: "post",
        data: {
          mid: this.songInfo.mid,
        },
        success: (res) => {
          this.musicLrcObj = res.data;
        },
      });
    },
    audioEnded() {
      this.$store.commit("playSong", false);
    },
    audioError() {
      let song = this.songInfo;
      this.$store.commit("playSong", false);
      if (this.audioRetryTimes < 5) {
        console.log("歌曲加载失败,正在准备重试");
        setTimeout(() => {
          this.audioRetryTimes++;
          this.$store.commit("playSong", song);
        }, 500);
      } else {
        console.error("尝试了5次,还是加载不出来了...");
      }
    },
    audioTimeUpdate() {
      if (
        this.songInfo &&
        this.$refs.audio.duration > 0 &&
        !isNaN(this.$refs.audio.duration)
      ) {
        let playInfo = {};
        playInfo.now = this.getSongTime(this.$refs.audio.currentTime);
        playInfo.total = this.getSongTime(this.$refs.audio.duration);
        playInfo.percent =
          parseInt(
            (this.$refs.audio.currentTime / this.$refs.audio.duration) * 10000
          ) / 100;
        playInfo.lrc = "";
        if (this.musicLrcObj) {
          for (let i = 0; i < this.musicLrcObj.length; i++) {
            if (i == this.musicLrcObj.length - 1) {
              playInfo.lrc = this.musicLrcObj[i].lrc;
              break;
            } else {
              if (
                this.$refs.audio.currentTime > this.musicLrcObj[i].time &&
                this.$refs.audio.currentTime < this.musicLrcObj[i + 1].time
              ) {
                playInfo.lrc = this.musicLrcObj[i].lrc;
                break;
              }
            }
          }
        }
        this.$store.commit("updatePlayInfo", playInfo);
      }
    },
    getSongTime(long) {
      long = parseInt(long);
      if (long == 0 || isNaN(long)) {
        return "00:00";
      }
      let string = "";
      string +=
        parseInt(long / 60) < 10
          ? "0" + parseInt(long / 60)
          : parseInt(long / 60);

      string += ":";
      string += long % 60 < 10 ? "0" + (long % 60) : long % 60;
      return string;
    },
    sendWssMessage(msg) {
      this.wss && this.wss.send(msg);
    },
    connectWebsocket() {
      this.loading_message = "Connecting...";
      this.wss = new WebSocket(this.config.websocketUrl);
      this.wss.onopen = () => {
        setTimeout(() => {
          this.wss.send(tool.getAccessToken());
          this.heartBeat();
        }, 0);
      };

      this.wss.onmessage = (evt) => {
        evt.data != "pong" && this.messageController(evt.data);
      };

      this.wss.onclose = () => {
        this.wss = false;
        clearTimeout(this.heartBeatTimer);
        if (!this.$store.state.showLogin) {
          this.reconnect();
        }
      };
    },
    reconnect() {
      if (this.wss) {
        return;
      }
      this.connectWebsocket();
    },
    heartBeat() {
      if (this.wss) {
        clearTimeout(this.heartBeatTimer);
        this.heartBeatTimer = setTimeout(() => {
          this.wss.send("ping");
          this.heartBeat();
        }, 30000);
      }
    },
    messageController(data) {
      let obj = false;
      try {
        obj = JSON.parse(data);
      } catch (e) {
        console.warn("Websocket: 消息解析失败");
      }
      if (obj) {
        console.log(obj);
        switch (obj.type) {
          case "success":
            this.$notify.success({
              title: "连接成功",
              message: "你已经成功连接到消息服务器",
              offset: 30,
              duration: 3000,
            });
            this.loading_message = false;
            break;
          default:
            switch (obj.type) {
              case "room":
                switch (obj.message.type) {
                  case "online":
                    this.$store.commit("updateOnlineList", obj.message.online);
                    break;
                  case "play":
                    this.$store.commit("playSong", obj.message.song);
                    break;
                  default:
                    this.$store.commit("addMessage", obj);
                }
                break;
              case "user":
                this.$store.commit("addPersonalMessage", obj);
                break;
              default:
            }
        }
      }
    },
    startTimer() {
      setInterval(() => {
        this.timeString = this.tool.formatTime(
          new Date(),
          "yyyy-MM-dd HH:mm:ss"
        );
      }, 1000);
    },
    /**
     * @description: 打开指定key的应用
     */
    openAppByKey(key) {
      this.$store.commit("openAppByKey", key);
    },
    /**
     * @description: 锁定屏幕
     */
    lockScreen() {
      this.$emit("lockScreen");
    },
    /**
     * @description: 关机
     */
    shutdown() {
      this.$emit("shutdown");
    },
    /**
     * @description: 注销登录
     */
    logout() {
      this.$emit("logout");
    },
  },
};
</script>

<style>
.top .el-dropdown {
  color: white !important;
  height: 100% !important;
}
.top .el-calendar-day {
  height: 30px !important;
}
.top .is-today {
  background: #4b9efb !important;
  color: white !important;
}

.el-dropdown__popper.el-popper[role="tooltip"] {
  /* top: 32px !important; */
  margin-top: -8px;
}

.el-dropdown-menu__item:hover {
  background-color: #4b9efb !important;
  color: white !important;
}

.el-dropdown-menu__item span:hover {
  color: white !important;
}

.el-dropdown-menu {
  padding: 0 !important;
  background: transparent !important;
}

.el-dropdown__popper.el-popper[role="tooltip"] {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(20px);
}

.el-dropdown-menu__item.line {
  height: 1px;
  background: rgba(0, 0, 0, 0.1);
  margin: 0px 15px;
}

.el-dropdown-menu__item span {
  color: #aaa;
}

.el-popper__arrow,
.el-popper__arrow::before {
  content: "" !important;
  width: 0;
  height: 0;
  opacity: 0;
  display: none !important;
}
</style>
<style scoped lang="scss">
.loading-message {
  position: fixed;
  left: 0;
  right: 0;
  text-align: center;
  bottom: 20%;
  z-index: 999;
  text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
  color: rgba(255, 255, 255, 0.8);
  font-size: 24px;
  animation: message 3s infinite linear;
}

.desktop {
  display: flex;
  flex-direction: column;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  color: white;
  overflow: hidden;
  text-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1);

  .top {
    height: 28px;
    background-color: rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(20px);
    display: flex;
    flex-direction: row;
    font-size: 14px;
    align-items: center;
    justify-content: center;
    padding: 0px 5px;
    z-index: 250;

    .space {
      flex-grow: 1;
    }

    .logo {
      height: 100%;
      align-items: center;
      justify-content: center;
      padding: 0px 15px;
      cursor: pointer;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;

      .el-select {
        position: absolute;
        opacity: 0;
      }
      .iconfont {
        font-size: 16px;
        margin-top: -3px;
      }
    }
    .logo:hover {
      background-color: rgba(255, 255, 255, 0.1);
    }
    .menu {
      display: flex;
      flex-direction: row;
      font-size: 13px;
      height: 100%;
      font-weight: 500;
      .item {
        font-size: 13px;
        padding: 0px 15px;
        display: inline-block;
        flex-grow: 1;
        cursor: pointer;
        display: flex;
        height: 100%;
        align-items: center;
        justify-content: center;
      }
      .item:hover {
        background-color: rgba(255, 255, 255, 0.1);
      }
    }

    .status {
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      height: 100%;
      .song {
        cursor: pointer;
      }
      .audio {
        cursor: pointer;
        padding: 0px 10px;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        position: relative;
        .iconfont {
          font-size: 20px;
        }
        .el-slider {
          position: absolute;
          top: 40px;
          height: 80px;
        }
      }
      .audio:hover {
        background-color: rgba(255, 255, 255, 0.1);
      }
      .datetime {
        cursor: pointer;
        padding: 0px 10px;
        height: 100%;
        font-family: 'Lucida Console';
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        position: relative;
        .el-calendar {
          color: #333;
          background: rgba(255, 255, 255, 0.98);
          position: fixed;
          top: 40px;
          right: 20px;
          width: 500px;
          border-radius: 10px;
        }
      }
      .datetime:hover {
        background-color: rgba(255, 255, 255, 0.1);
      }
      .notification {
        cursor: pointer;
        padding: 0px 10px;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        .iconfont {
          font-size: 20px;
        }
        .notification:hover {
          background-color: rgba(255, 255, 255, 0.1);
        }
      }
    }
  }
  .body {
    flex-grow: 1;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    position: relative;

    .desktop-app {
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-end;
      padding: 20px;
      flex-wrap: wrap-reverse;
    }

    .app-item {
      padding: 10px 0px;
      flex-direction: column;
      text-align: center;
      text-shadow: 0px 0px 2px rgb(0 0 0 / 50%);
      cursor: pointer;
      border-radius: 10px;
      border: 2px solid transparent;
      justify-content: center;
      align-items: center;
      width: 80px;
      .icon {
        border-radius: 10px;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
      }
      .iconfont {
        font-size: 28px;
        border-radius: 10px;
        padding: 8px;
      }
      .title {
        font-size: 12px;
        margin-top: 5px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
      }
    }

    .app-item:hover {
      border: 2px solid rgba(255, 255, 255, 0.5);
    }

    .contextmenu {
      position: absolute;
      background: rgba(255, 255, 255, 0.9);
      border-radius: 5px;
      box-shadow: 0px 0px 10px rgb(0 0 0 / 30%);
      color: #333;
      font-size: 14px;
      text-align: left;
      width: 200px;
      overflow: hidden;
      padding: 2px 0px;
      text-shadow: none;
      z-index: 100;
      hr {
        border: none;
        border-top: 1px solid #ddd;
      }
      div {
        cursor: pointer;
        font-size: 13px !important;
        color: #333;
        border-radius: 5px;
        line-height: 2;
        padding: 0px 12px;
        display: flex;
        align-items: center;
        margin: 3px 5px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      div:hover {
        background: #4b9efb;
        color: white;
        border-radius: 5px;
      }
    }
  }

  .footer {
    position: fixed;
    left: 5px;
    right: 5px;
    bottom: 5px;
    justify-content: center;
    align-items: center;
    display: flex;
    flex-direction: row;
    z-index: 250;
    .dock {
      background-color: rgba(255, 255, 255, 0.1);
      border: 1px solid rgba(255, 255, 255, 0.1);
      box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
      backdrop-filter: blur(20px);
      border-radius: 10px;
      flex-direction: row;
      display: flex;
      padding: 2px;

      .jump {
        animation: jumpAnimation 0.8s ease 1;
      }
      .title {
        display: none;
      }
      .item {
        padding: 3px;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        .iconfont {
          cursor: pointer;
          border-radius: 20px;
          padding: 2px;
          display: inline-block;
          background-color: rgba(255, 255, 255, 0.1);
          border-radius: 10px;
          height: 30px;
          width: 30px;
          text-align: center;
          font-size: 24px;
          display: flex;
          align-items: center;
          justify-content: center;
          transition: transform 0.3s, margin 0.3s;
        }
      }
      .item:hover {
        .iconfont {
          transform: scale(2) translateY(-10px);
          margin: 0px 15px;
          box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
        }
        .title {
          position: absolute;
          display: inherit;
          word-break: keep-all;
          background: rgba(0, 0, 0, 0.3);
          box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
          border-radius: 10px;
          padding: 5px 10px;
          font-size: 12px;
          animation: dockTitleAnimation 0.5s ease 1 forwards;
        }
      }
      .dot {
        width: 3px;
        height: 3px;
        background: rgba(0, 0, 0, 0.8);
        position: absolute;
        bottom: 0px;
        border-radius: 5px;
        display: inline-block;
        font-size: 0;
      }
      .nearby .iconfont {
        transform: scale(1.6) translateY(-8px);
        margin: 0px 12px;
        box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
      }
      .nearby1 .iconfont {
        transform: scale(1.2) translateY(-6px);
        margin: 0px 9px;
        box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
      }
      .nearby2 .iconfont {
        transform: scale(1.1) translateY(-5px);
        margin: 0px 7px;
        box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
      }
    }
  }
}
</style>